import time
import random
from . import chess
from . import score
from . import min_max
from . import cache

class BoardExplorer:
	def __init__(self, min_depth, max_depth, max_time):
		self.min_depth = min_depth
		self.max_depth = max_depth
		self.max_time = max_time
		self.cache = cache.AlphaBetaCache()
	def run(self, board):
		self.start_time = time.time()
		self.explored = 0
		self.from_cache = 0
		self.cut_off = 0 # 剪枝数目
		cur_depth = 0
		cur_node = None
		cur_explored = 0
		min_max.Node.explorer = self
		for depth in range(self.min_depth,self.max_depth+1): # 迭代加深
			self.depth = depth
			node = min_max.Node(board, height=depth)
			node.alpha, node.beta = -1E6, 1E6
			node.moves = []
			try:
				search(node)
				cur_node,cur_explored,cur_depth = node,self.explored,depth
			except TimeoutError:
				break
		elapsed = time.time()-self.start_time
		print(f'计算:{self.explored}(有效:{cur_explored},剪枝:{self.cut_off}) 深度:{cur_depth} 缓存:{self.from_cache} 用时:{round(elapsed*100)/100}')
		return cur_node
	def time_is_up(self):
		elapsed = time.time()-self.start_time
		return elapsed > self.max_time

def search(node):
	explorer = min_max.Node.explorer
	if (explorer.depth>explorer.min_depth) and explorer.time_is_up():
		raise TimeoutError()
	if min_max.is_terminal(node):
		node.score = node.heuristic_score
		return
	explorer.explored += 1
	node.score = -1E6
	children = min_max.create_child_nodes(node)
	random.shuffle(children)
	children.sort(key=lambda c: c[1].heuristic_score)
	children.sort(key=lambda c: c[1].score is None)
	for move, child in children:
		child.alpha, child.beta = -node.beta, min(-node.alpha, -node.score)
		if child.score is None:
			search(child)
		else:
			explorer.from_cache += 1
		if node.score < -child.score:
			node.score = -child.score
			node.best_move = move
		if node.score >= node.beta:
			node.best_move = None
			explorer.cut_off += 1
			break
	explorer.cache.add_to_cache(node)
	if node.moves is not None:
		node.moves = [(-child.score, move) for move, child in children]

explorer = None
def auto_move(board):
	global explorer
	if explorer is None:
		explorer = BoardExplorer(4, 5, 10) # 搜索深度，搜索秒数
	node = explorer.run(board) 
	min_max.print_moves(node)
	return None if node.best_move is None else node.best_move[2:]
